

module Sync_FIFO(
    input wr_en,rd_en,clk,reset,
    input [7:0] dataIn,
    output [7:0] dataOut,
    output full,empty
    );
parameter fifo_len = 8;
reg [3:0] fifo_cnt; // fifo内部数据个数
reg [7:0] dataOut_reg; 
reg [2:0] addr_wr;
reg [2:0] addr_rd; 
reg full_reg,empty_reg;
reg [7:0] RAM [fifo_len-1:0];

// 写
always @(posedge clk or posedge reset)
if (reset) begin
    addr_wr <= 3'd0;
    RAM[addr_wr] <= 8'd0;
end
else if (full_reg == 1'd0 && wr_en) begin
    addr_wr <= addr_wr + 1'b1;
    RAM[addr_wr] <= dataIn;
end
else begin
    addr_wr <= addr_wr;
    RAM[addr_wr] <= RAM[addr_wr];
end

// 读
always @(posedge clk or posedge reset)
if (reset) begin
    addr_rd <= 3'd0;
    dataOut_reg <= 8'd0;
end
else if (empty_reg == 1'd0 && rd_en) begin
    addr_rd <= addr_rd + 1'b1;
    dataOut_reg <= RAM[addr_rd];
end
else begin
    addr_rd <= addr_rd;
    dataOut_reg <= dataOut_reg;
end

// 数据数
always @(posedge clk or posedge reset)
 if (reset)
    fifo_cnt <= 3'd0;
 else if (wr_en == 1'd1 && rd_en == 1'd0) begin
    fifo_cnt <= fifo_cnt + 1'd1;
    end
 else if (wr_en == 1'd0 && rd_en == 1'd1) begin
    fifo_cnt <= fifo_cnt - 1'd1;
    end
 else begin
    fifo_cnt <= fifo_cnt;
 end

// 满，空
 always @(*)
 if  (fifo_cnt == (fifo_len)) begin
    full_reg <= 1'd1;
    empty_reg <= 1'd0;
    end
 else if  (fifo_cnt == 3'd0) begin
    full_reg <= 1'd0;
    empty_reg <= 1'd1;
 end
 else begin
    full_reg <= 1'd0;
    empty_reg <= 1'd0;
 end
 
 assign dataOut = dataOut_reg;
 assign full    = full_reg;
 assign empty   = empty_reg;
   
endmodule
